﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

using QuickShot.Utility;
using QuickShot.Windows;

namespace QuickShot.Forms
{
    public partial class RegionForm : SingleLayeredForm
    {
        private Rectangle _regionRectangle = Rectangle.Empty;
        public Rectangle RegionRectangle 
        {
            get 
            { 
                return _regionRectangle;
            }
            set 
            { 
                _regionRectangle = value;
            }
        }

        private bool drawing = false;
        private Point startLocation = Point.Empty;
        private Point cursorLocation = Point.Empty;
        private Brush fillBrush = new SolidBrush(Color.FromArgb(50, 30, 130, 255));
        private Pen borderPen = new Pen(Color.FromArgb(50, 204, 229, 255)) 
        { 
            DashStyle = DashStyle.Solid 
        };

        public RegionForm()
        {
            InitializeComponent();
            Location = ScreenData.StartPoint;
            Size = ScreenData.ScreenSize;
            TopMost = true;
            Cursor = Cursors.Cross;
            ShowInTaskbar = false;
        }

        private void RegionForm_MouseDown(object sender, MouseEventArgs e)
        {
            this.startLocation = e.Location;
            this.drawing = true;
        }

        private void RegionForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (!this.drawing) return;
            this.cursorLocation = e.Location;
            this.Invalidate();
        }

        private void RegionForm_MouseUp(object sender, MouseEventArgs e)
        {
            this.drawing = false;
            for (int a = 50; a > 0; a -= 12)
            {
                fillBrush = new SolidBrush(Color.FromArgb(a, 30, 130, 255));
                borderPen = new Pen(Color.FromArgb(a, 204, 229, 255)) 
                { 
                    DashStyle = DashStyle.Solid 
                };
                this.Invalidate();
            }

            _regionRectangle.Location = PointToScreen(RegionRectangle.Location);

            DialogResult = DialogResult.OK;
        }

        private void RegionForm_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

            _regionRectangle = new Rectangle(Math.Min(this.startLocation.X, this.cursorLocation.X), Math.Min(this.startLocation.Y, this.cursorLocation.Y), 
                Math.Abs(this.startLocation.X - this.cursorLocation.X), Math.Abs(this.startLocation.Y - this.cursorLocation.Y));

            e.Graphics.FillRectangle(this.fillBrush, _regionRectangle);
            e.Graphics.DrawRectangle(this.borderPen, _regionRectangle);

            //Dimensions Drawing
            //e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(100, 0, 5, 60)), new Rectangle(new Point(_regionRectangle.Right - 75, _regionRectangle.Bottom - 31), new Size(67, 23)));
            //e.Graphics.DrawRectangle(borderPen, new Rectangle(new Point(_regionRectangle.Right - 75, _regionRectangle.Bottom - 31), new Size(67, 23)));
            //e.Graphics.DrawString(string.Format("{0}x{1}", _regionRectangle.Width, _regionRectangle.Height), new Font("Segoe UI", 9.25f), Brushes.White, new Point(_regionRectangle.Right - 67, _regionRectangle.Bottom - 27));
        }

    }

    public class SingleLayeredForm : Form
    {
        public new event PaintEventHandler Paint;

        public SingleLayeredForm()
        {
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.FormBorderStyle = FormBorderStyle.FixedSingle;
            this.StartPosition = FormStartPosition.Manual;
        }

        protected override CreateParams CreateParams
        {
            get
            {
                if (DesignMode) return base.CreateParams;
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle = createParams.ExStyle | 0x80000;
                return createParams;
            }
        }

        public void SetBitmap(Bitmap bitmap)
        {
            if (!IsHandleCreated || DesignMode) return;
            IntPtr oldBits = IntPtr.Zero;
            IntPtr screenDC = WinAPI.GetDC(IntPtr.Zero);
            IntPtr hBitmap = IntPtr.Zero;
            IntPtr memDC = WinAPI.CreateCompatibleDC(screenDC);
            try
            {
                Point topLocation = new Point(this.Left, this.Top);
                Size bitmapSize = new Size(bitmap.Width, bitmap.Height);
                WinAPI.BLENDFUNCTION blendFunc = new WinAPI.BLENDFUNCTION();
                Point sourceLocation = Point.Empty;
                hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                oldBits = WinAPI.SelectObject(memDC, hBitmap);
                blendFunc.BlendOp = WinAPI.AC_SRC_OVER;
                blendFunc.SourceConstantAlpha = 255;
                blendFunc.AlphaFormat = WinAPI.AC_SRC_ALPHA;
                blendFunc.BlendFlags = 0;
                WinAPI.UpdateLayeredWindow(Handle, screenDC, ref topLocation, ref bitmapSize, memDC, ref sourceLocation, 0, ref blendFunc, WinAPI.ULW_ALPHA);
            }
            finally
            {
                if (hBitmap != IntPtr.Zero)
                {
                    WinAPI.SelectObject(memDC, oldBits);
                    WinAPI.DeleteObject(hBitmap);
                }
                WinAPI.ReleaseDC(IntPtr.Zero, screenDC);
                WinAPI.DeleteDC(memDC);
            }
        }

        public new void Invalidate()
        {
            using (Bitmap bitmap = new Bitmap(this.ClientSize.Width, this.ClientSize.Height))
            {
                using (Graphics graphics = Graphics.FromImage(bitmap))
                {
                    graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    //graphics.CompositingMode = CompositingMode.SourceCopy;
                    if (this.Paint != null)
                        this.Paint(this, new PaintEventArgs(graphics, Rectangle.Empty));
                }
                SetBitmap(bitmap);
            }
        }
    }

}
